
       #include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <libgen.h>
#include <pwd.h>
#include <grp.h>

int ls_file(char *fname)
{
    //get file status
    struct stat fstat;
    int r, i;
    char ftime[64];
    if((r = lstat(fname,&fstat)) < 0)
    {
        perror("lstat file failed ");
        exit(1);
    }
    //get file type
    if(S_ISREG(fstat.st_mode))
    {
        printf( "%c",'-' ) ;
    }
    else if (S_ISDIR(fstat.st_mode))
    {
        printf ( "%c",'d' ) ;
    }
    else if (S_ISLNK(fstat.st_mode))
    {
        printf ( "%c",'l') ;
    }
    else if (S_ISCHR(fstat.st_mode))
    {
        printf ( "%c",'c') ;
    }
    else if (S_ISFIFO(fstat.st_mode))
    {
        printf ( "%c",'p') ;
    }
    else if (S_ISSOCK(fstat.st_mode))
    {
        printf ( "%c",'s') ;
    }
    else if (S_ISBLK(fstat.st_mode))
    {
        printf ( "%c",'b') ;
    }
    else
    {
        //unknown type
        printf ( "%c",'?') ;
    }

    //get file rwx
    char *t1 = "rwxrwxrwx";
    for (i=8; i>= 0; i--)
    {
        if (fstat.st_mode & (1 << i))       //print rwx
            printf("%c", t1[8-i]);
        else
            printf("%c", '-');
    }

    printf("%4d ", fstat.st_nlink);             // link count

    //uid
    struct passwd *user;
    user = getpwuid(fstat.st_uid);
    printf("%s\t",user->pw_name);

    // gid
    struct group *gdata;
    gdata = getgrgid(fstat.st_gid);
    printf("%s  ", gdata->gr_name);

    printf("%8d ", fstat.st_size) ;         // file size
    //printf ("%s",basename(fname)) ;   // print file basename
    struct tm *block;
    block = localtime(&fstat.st_mtime);
    printf("%4d-%02d-%02d %02d:%02d ",
           block->tm_year+1900, block->tm_mon+1, block->tm_mday,
           block->tm_hour, block->tm_min);

    //print name
    printf("%s",basename(fname));
    // print -> linkname if symbolic file
    if (S_ISLNK(fstat.st_mode))
    {
        char buf[100];
        int result = readlink(fname,buf,100-1);
        if (result < 0)
        {
            perror("readlink ");
            exit(1);
        }
        printf(" -> %s",buf);   //print link file content
    }
    printf("\n");
}
int ls_dir(char *dname)
{
    //use opendir( ), readdir( ) ; then ca11 1s_file(name)
    DIR *dp;
    struct dirent *sdp;
    dp = opendir(dname);
    if(dp==NULL)
    {
        perror("opendir failed ");
        exit(1);
    }
    int len = strlen(dname);
    while( (sdp = readdir(dp)) != NULL)
    {
        if(sdp->d_name[0]=='.')
        {
            continue;
        }
        char filename[1024];
        int i;
        for(i=0; i<len; i++)
        {
            filename[i] = dname[i];
        }
        filename[len] = '/';
        len++;
        for(i=0; sdp->d_name[i]!='\0'; i++)
        {
            filename[i+len]=sdp->d_name[i];
        }
        filename[i+len]='\0';
        len--;
        ls_file(filename);
    }
    closedir(dp);
}
int main (int argc, char *argv[])
{
    //get file status
    struct stat sbuf;
    int r;
    char cwd[1024];
    getcwd(cwd,1023);
    char *route = strcat(cwd,"/");
    if(argc == 2)
    {
        route = strcat(cwd,argv[1]);
    }
    r = lstat(route,&sbuf);
    if(r<0)
    {
        perror("lstat ");
        exit(1);
    }
    if(S_ISDIR(sbuf.st_mode))
    {
        ls_dir(route);
    }
    else
    {
        ls_file(route);
    }
    return 0;
}


